/**
* @file list_image.cpp
*
*	 Nel file list_image.cpp viene implementata la classe List_Image
*	
* @author Favale Angelo
* @author Fagioli Alessio
*
* @version 1.0
*/

#include "list_image.h"

List_Image::List_Image()
{
	first = NULL;
	pthread_mutex_init( &lock ,NULL );
}

struct node_image * List_Image::findNodo(char * nome_file)
{
	struct node_image * cercatore;
	char file[BUFFER_SIZE];

	sprintf(file, "foto/%s", nome_file);

	pthread_mutex_lock( &lock );

	for( cercatore = first; cercatore != NULL && strcmp( cercatore->name, file ); cercatore = cercatore->next);

	pthread_mutex_unlock( &lock );

	return cercatore;
}


void List_Image::add_image (char * name_file)
{

	struct node_image * c, *scroll;

	c=new struct node_image;
	char file[BUFFER_SIZE];

	sprintf(file, "foto/%s", name_file);
	
	strcpy(c->name,file);

	pthread_mutex_init( &c->mutex ,NULL );
	pthread_cond_init( &c->bloccoLettori, NULL);
	pthread_cond_init( &c->bloccoScrittori, NULL);
	c->lettoriAttivi = 0;
	c->scrittoreAttivo = false;
	c->lettoriBloccati = 0;
	c->scrittoriBloccati = 0;
	
	c->next=NULL;

	pthread_mutex_lock( &lock );

	if (first==NULL)
		first=c;	
	else
		{ 
		scroll=first;
		while (scroll-> next!= NULL)
			scroll=scroll->next;
		scroll->next=c;
		
		}

	pthread_mutex_unlock( &lock );

}


void List_Image::get_list (char * buffer)
{
	
	memset(buffer,0,BUFFER_SIZE);

	pthread_mutex_lock( &lock );

	struct node_image *scroll=first;
	
	while (scroll!=NULL)
	{
		strcat(buffer,scroll->name);
		if (scroll->next != NULL)
			strcat(buffer, ";");
		else
			strcat(buffer, "#");
	
		scroll = scroll->next;
	}

	pthread_mutex_unlock( &lock );
}


void List_Image::richiestaScrittura (char * nome_file)
{
	struct node_image * nodo;
	nodo = findNodo( nome_file );
	
	if( nodo == NULL )
	{
		add_image( nome_file );
		nodo = findNodo( nome_file );
	}
	pthread_mutex_lock( &nodo->mutex );
	if( nodo->lettoriAttivi > 0 || nodo->scrittoreAttivo )
	{
		nodo->scrittoriBloccati++;
		while( nodo->lettoriAttivi > 0 || nodo->scrittoreAttivo )		
			pthread_cond_wait( &nodo->bloccoScrittori, &nodo->mutex );
		nodo->scrittoriBloccati--;
	}
	nodo->scrittoreAttivo = true;	
	pthread_mutex_unlock( &nodo->mutex );
}


void List_Image::rilascioScrittura (char * nome_file)
{
	struct node_image * nodo;

	nodo = findNodo( nome_file );
	pthread_mutex_lock( &nodo->mutex );
	nodo->scrittoreAttivo = false;
	if( nodo->lettoriBloccati > 0 )
		pthread_cond_broadcast( &nodo->bloccoLettori );
	else
		if( nodo->scrittoriBloccati > 0)
			pthread_cond_signal( &nodo->bloccoScrittori );
	pthread_mutex_unlock( &nodo->mutex );
}


void List_Image::richiestaLettura (char * nome_file)
{
	struct node_image * nodo;
	
	nodo = findNodo( nome_file );
	if( nodo == NULL )
	{
		printf("nn ho trovato il nodo\n");
	}
	pthread_mutex_lock( &nodo->mutex );
	if( nodo->scrittoriBloccati > 0 || nodo->scrittoreAttivo )
	{
		nodo->lettoriBloccati++;
		while( nodo->scrittoriBloccati > 0 || nodo->scrittoreAttivo )
			pthread_cond_wait( &nodo->bloccoLettori, &nodo->mutex );
		nodo->lettoriBloccati--;
	}
	nodo->lettoriAttivi++;
	if( nodo->lettoriBloccati > 0 )
		pthread_cond_broadcast( &nodo->bloccoLettori );
	pthread_mutex_unlock( &nodo->mutex );
}


void List_Image::rilascioLettura (char * nome_file)
{
	struct node_image * nodo;
	nodo = findNodo( nome_file );
	if( nodo == NULL )
	{
		printf("Errore nella ricerca del nodo da rilasciare la lettura\n");
	}
	pthread_mutex_lock( &nodo->mutex );
	nodo->lettoriAttivi--;
	if( nodo->lettoriAttivi == 0 && nodo->scrittoriBloccati > 0 )
		pthread_cond_signal( &nodo->bloccoScrittori );
	pthread_mutex_unlock( &nodo->mutex );
}

